/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "device_mgr.h"

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>


#include <string.h>
#include "los_task.h"        // 根据实际路径调整


#include "iot_errno.h"
#include "iot_i2c.h"
#include "iot_pwm.h"
#include "iot_gpio.h"

#include "lcd.h"
#include "picture.h"
#include "door.h"

bool g_is_lcd_init = false;

/***************************************************************
* 函数名称: i2c_dev_init
* 说    明: i2c设备初始化
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void i2c_dev_init(void)
{
    printf("i2c_dev_init enter...\n");

    IoTI2cInit(I2C_HANDLE, EI2C_FRE_400K);

    // 光照传感器初始化
    uint8_t send_data[3] = {0x01};
    uint32_t send_len = 1;
    uint32_t ret = LzI2cWrite(I2C_HANDLE, BH1750_I2C_ADDRESS, send_data, send_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++BH1750 init failed+++++++++\n");
    }

    // 矩阵键盘初始化
    send_data[0] = 0xFF;
    send_len = 1;
    ret = LzI2cWrite(I2C_HANDLE, KEYBOARD_I2C_ADDRESS, send_data, send_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++Keyboard init failed+++++++++\n");
    }

    // 温湿度传感器初始化
    // 传感器软复位
    send_data[0] = 0xBA;
    // send_data[1] = 0x08;
    // send_data[2] = 0x00;
    send_len = 1;
    ret = LzI2cWrite(I2C_HANDLE, AHT20_I2C_ADDRESS, send_data, send_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++AHT20 reset failed: %d+++++++++\n", ret);
    }
    LOS_TaskDelay(100);

    // 传感器校准
    send_data[0] = 0xBE;
    send_data[1] = 0x08;
    send_data[2] = 0x00;
    send_len = 3;
    ret = LzI2cWrite(I2C_HANDLE, AHT20_I2C_ADDRESS, send_data, send_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++AHT20 carlibrate failed: %d+++++++++\n", ret);
    }
}

void gpio_dev_init(void)
{
    // IoTGpioInit(GPIO_BODY_INDUCTION);
    // IoTGpioSetDir(GPIO_BODY_INDUCTION, IOT_GPIO_DIR_IN);
    // IoTGpioSetPull(GPIO_BODY_INDUCTION, IOT_GPIO_PULL_UP);
    // IoTGpioSetIntType(GPIO_BODY_INDUCTION, IOT_GPIO_INT_TYPE_EDGE_FALLING);
    // IoTGpioRegisterIsrFunc(GPIO_BODY_INDUCTION, GPIO_INT_CB_FUNC, NULL);
    // 风扇控制引脚初始化
    IoTGpioInit(MOTOR_PWM_B1A);
    IoTGpioSetDir(MOTOR_PWM_B1A, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(MOTOR_PWM_B1A, IOT_GPIO_VALUE0);
    IoTGpioInit(MOTOR_PWM_B2A);
    IoTGpioSetDir(MOTOR_PWM_B2A, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(MOTOR_PWM_B2A, IOT_GPIO_VALUE0);

    IoTGpioInit(LIGHT_CTL_PIN);
    IoTGpioSetDir(LIGHT_CTL_PIN, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE0);
}
int door_init(void)
{
    sg90_init(DOOR_ENTRY_PIN);
    sg90_init(DOOR_GARAGE_PIN);
    sg90_init(WINDOW_PIN);
    // IoTGpioSetDir(DOOR_ENTRY_PIN, IOT_GPIO_DIR_OUT);
    // IoTGpioSetDir(DOOR_GARAGE_PIN, IOT_GPIO_DIR_OUT);
    // IoTGpioSetDir(WINDOW_PIN, IOT_GPIO_DIR_OUT);
    // IoTGpioSetOutputVal(DOOR_ENTRY_PIN, IOT_GPIO_VALUE0);
    // IoTGpioSetOutputVal(DOOR_GARAGE_PIN, IOT_GPIO_VALUE0);
    // IoTGpioSetOutputVal(WINDOW_PIN, IOT_GPIO_VALUE0);
    return 0;
}

/***************************************************************
* 函数名称: light_dev_init
* 说    明: rgb灯设备初始化
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void light_dev_init(void)
{
    // IoTGpioInit(LED_R_GPIO_HANDLE);
    // IoTGpioInit(LED_G_GPIO_HANDLE);
    // IoTGpioInit(LED_B_GPIO_HANDLE);
    // IoTGpioSetDir(LED_R_GPIO_HANDLE, IOT_GPIO_DIR_OUT);
    // IoTGpioSetDir(LED_G_GPIO_HANDLE, IOT_GPIO_DIR_OUT);
    // IoTGpioSetDir(LED_B_GPIO_HANDLE, IOT_GPIO_DIR_OUT);
}

/***************************************************************
* 函数名称: light_set_state
* 说    明: 控制灯状态
* 参    数: bool state true：打开 false：关闭
* 返 回 值: 无
***************************************************************/
// void light_set_state(bool state)
// {
//     static bool last_state = false;

//     if (state == last_state)
//     {
//         return;
//     }

//     if (state)
//     {
//         IoTGpioSetOutputVal(LED_R_GPIO_HANDLE, IOT_GPIO_VALUE1);
//         IoTGpioSetOutputVal(LED_G_GPIO_HANDLE, IOT_GPIO_VALUE1);
//         IoTGpioSetOutputVal(LED_B_GPIO_HANDLE, IOT_GPIO_VALUE1);
//     }
//     else
//     {
//         IoTGpioSetOutputVal(LED_R_GPIO_HANDLE, IOT_GPIO_VALUE0);
//         IoTGpioSetOutputVal(LED_G_GPIO_HANDLE, IOT_GPIO_VALUE0);
//         IoTGpioSetOutputVal(LED_B_GPIO_HANDLE, IOT_GPIO_VALUE0);
//     }

//     last_state = state;
// }

/***************************************************************
* 函数名称: lcd_dev_init
* 说    明: lcd初始化
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void lcd_dev_init(void)
{
    lcd_init();
    lcd_fill(0, 0, LCD_W, LCD_H, LCD_WHITE);
}

/***************************************************************
 * 
* 函数名称: lcd_load_ui
* 说    明: 加载lcd ui
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void lcd_load_ui(void)
{
    float t = 0;
    uint8_t cur_sizey = 12;
    // lcd_show_chinese(81, 0, (uint8_t*)"智慧小屋", LCD_BLUE, LCD_WHITE, 32, 0);
    printf("************load UI***********\n");
    lcd_show_picture(50, 0, 135, 40, &gImage_company_logo[0]);
    lcd_draw_line(0, 42, LCD_W, 42, LCD_DARKBLUE);
    lcd_show_string(32, 45, "Smart House", LCD_RED, LCD_WHITE, 32, 0);
    lcd_show_string(0, 80, "Temperature  : ", LCD_BLUE, LCD_WHITE, 16, 0);
    lcd_show_string(0, 100, "Humidity     : ", LCD_BLUE, LCD_WHITE, 16, 0);
    lcd_show_string(0, 120, "Illumination : ", LCD_BLUE, LCD_WHITE, 16, 0);
    lcd_draw_line(0, 160, LCD_W, 160, LCD_DARKBLUE);
    lcd_show_string(0, 165, "Entry door  : ", LCD_BRED, LCD_WHITE, 16, 0);
    lcd_show_string(0, 185, "Garage door : ", LCD_BRED, LCD_WHITE, 16, 0);
    lcd_show_string(0, 205, "Window      : ", LCD_BRED, LCD_WHITE, 16, 0);
    // lcd_show_int_num(48, 160, LCD_W, 3, LCD_BLUE, LCD_WHITE, 16);
    // lcd_show_string(80, 160, "LCD_H:", LCD_BLUE, LCD_WHITE, 16, 0);
    // lcd_show_int_num(128, 160, LCD_H, 3, LCD_BLUE, LCD_WHITE, 16);
    // lcd_show_string(80, 160, "LCD_H:", LCD_BLUE, LCD_WHITE, 16, 0);
    // lcd_show_string(0, 190, "Increaseing Num:", LCD_BLACK, LCD_WHITE, 16, 0);
    // lcd_show_float_num1(128, 190, t, 4, LCD_BLACK, LCD_WHITE, 16);
    t += 0.11;

    // lcd_fill(0, 0, LCD_W, LCD_H, LCD_WHITE);
    // lcd_show_chinese(0, 220, "小凌派", LCD_RED, LCD_WHITE, cur_sizey, 0);
    if (cur_sizey == 12)
        cur_sizey = 16;
    else if(cur_sizey == 16)
        cur_sizey = 24;
    else if(cur_sizey == 24)
        cur_sizey = 32;
    else
        cur_sizey = 12;

    g_is_lcd_init = true;
}

/***************************************************************
* 函数名称: lcd_set_human_state
* 说    明: 设置人体状态显示
* 参    数: bool state true：显示"有人" false：显示"无人"
* 返 回 值: 无
***************************************************************/
void lcd_set_human_state(bool state)
{
    if (state)
    {
        lcd_show_chinese(120, 75, (uint8_t*)"有人", LCD_RED, LCD_WHITE, 24, 0);
    }
    else
    {
        lcd_show_chinese(120, 75, (uint8_t*)"无人", LCD_RED, LCD_WHITE, 24, 0);
    }
}

/***************************************************************
* 函数名称: lcd_set_light_state
* 说    明: 设置灯状态显示
* 参    数: bool state true：显示"打开" false：显示"关闭"
* 返 回 值: 无
***************************************************************/
void lcd_set_light_state(bool state)
{
    if (state)
    {
        lcd_show_chinese(120, 120, (uint8_t*)"开启", LCD_RED, LCD_WHITE, 24, 0);
    }
    else
    {
        lcd_show_chinese(120, 120, (uint8_t*)"关闭", LCD_RED, LCD_WHITE, 24, 0);
    }
}

/***************************************************************
* 函数名称: lcd_set_auto_state
* 说    明: 设置自动模式状态显示
* 参    数: bool state true：显示"打开" false：显示"关闭"
* 返 回 值: 无
***************************************************************/
void lcd_set_auto_state(bool state)
{
    if (state)
    {
        lcd_show_chinese(120, 150, (uint8_t*)"开启", LCD_RED, LCD_WHITE, 24, 0);
    }
    else
    {
        lcd_show_chinese(120, 150, (uint8_t*)"关闭", LCD_RED, LCD_WHITE, 24, 0);
    }
}

void delay_us(uint32_t us)
{
    // 这里使用LOS_TaskDelayUs函数来实现延时
    LOS_TaskDelay(us);
}


/***************************************************************
 * 函数名称: body_induction_get_state
 * 说    明: 获取人体感应状态
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
bool body_induction_get_state()
{
    IotGpioValue value = IOT_GPIO_VALUE0;

    // IoTGpioGetInputVal(GPIO_BODY_INDUCTION, &value);

    if (value) 
    {
        return true;
    }
    else
    {
        return false;
    }

    printf("body_induction_get_state: %d\n", value);
}

/***************************************************************
 * 函数名称: body_induction_dev_init
 * 说    明: 人体感应传感器初始化
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void body_induction_dev_init(void)
{
//     IoTGpioInit(GPIO_BODY_INDUCTION);
//     IoTGpioSetDir(GPIO_BODY_INDUCTION, IOT_GPIO_DIR_IN);
}

uint32_t mq2_dev_init(iss_mq2_dev_s *adc)
{
    if (PinctrlInit(adc->adc) != 0)
    {
        printf("adc pin %d init failed\n", adc->adc.gpio);
        return 1;
    }
    if (LzSaradcInit() != 0)
    {
        printf("saradc  %d init failed\n", adc->port);
        return 1;
    }
    
    volatile GRF_SOC_CON29 *soc = (GRF_SOC_CON29*)&GRF->SOC_CON29;
    /*配置ADC外部参考电压grf_saradc_vol_sel=0，内部参考电压grf_saradc_vol_sel=1,rw.grf_saradc_vol_sel对应位写使能*/
    soc->grf_saradc_vol_sel = 1;
    soc->grf_saradc_vol_sel    = 0;
    soc->grf_saradc_vol_sel = 0;
    
    adc->init = 1;
    return 0;
}
float adc_get_voltage(void)
{
    unsigned int ret = IOT_SUCCESS;
    unsigned int data = 0;

    ret = IoTAdcGetVal(MQ2_PIN, &data);

    if (ret != IOT_SUCCESS)
    {
        printf("%s, %s, %d: ADC Read Fail\n", __FILE__, __func__, __LINE__);
        return 0.0;
    }

    return (float)(data * 3.3 / 1024.0);
}
void calibrate_mq2_ppm(void) 
{
  float voltage = adc_get_voltage();
  float rs = (5 - voltage) / voltage * RL;

  m_r0 = rs / powf(CAL_PPM / 613.9f, 1 / -2.074f);
}

float get_mq2_ppm(void)
{
    float voltage = adc_get_voltage();
    float rs = (5 - voltage) / voltage * RL;
    float ppm = powf(m_r0 / rs, 2.074f) * 613.9f;

    return ppm;
}

int get_light_value(float *lux)
{
    // 启动光照传感器
    uint8_t send_data[1] = {0x10};
    uint32_t send_len = 1;
    uint32_t ret = LzI2cWrite(I2C_HANDLE, BH1750_I2C_ADDRESS, send_data, send_len);
    LOS_Msleep(180); // 等待传感器稳定
    
    // 读取光照值
    uint8_t recv_data[2] = {0};
    uint32_t receive_len = 2;
    ret |= LzI2cRead(I2C_HANDLE, BH1750_I2C_ADDRESS, recv_data, receive_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++BH1750 I2C read error: %d+++++++++\n", ret);
        return -1;
    }

    *lux = (float)(((recv_data[0]<<8) + recv_data[1])/1.2);

    // LCD 显示光照强度值
    // printf("~~~~~~~~~Light: %.2f lux~~~~~~~~~\n", *lux);
    if (g_is_lcd_init)
    {
        char ill_value[16] = {0};
        sprintf(ill_value, "%d lux  ", (int)*lux);
        lcd_show_string(130, 120, ill_value, LCD_BLUE, LCD_WHITE, 16, 0);
    }
    
    return 0;
}

int get_tmp_hum_value(float *temperature, float *humidity)
{
    // 启动温湿度传感器
    uint8_t send_data[3] = {0xAC, 0x33, 0x00};
    uint32_t send_len = 3;
    uint32_t ret = LzI2cWrite(I2C_HANDLE, AHT20_I2C_ADDRESS, send_data, send_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++AHT20 I2C start read error: %d+++++++++\n", ret);
        return ret;
    }
    LOS_Msleep(180); // 等待传感器稳定
    
    // 读取温湿度值
    uint8_t recv_data[6] = {0};
    uint32_t receive_len = 6;
    ret |= LzI2cRead(I2C_HANDLE, AHT20_I2C_ADDRESS, recv_data, receive_len);
    if (ret != LZ_HARDWARE_SUCCESS)
    {
        printf("+++++++++AHT20 I2C read error: %d+++++++++\n", ret);
        return ret;
    }
    uint32_t humidity_raw = ((uint32_t)recv_data[1] << 12) | ((uint32_t)recv_data[2] << 4) | (recv_data[3] >> 4);
    uint32_t temp_raw = (((uint32_t)recv_data[3] & 0x0F) << 16) | ((uint32_t)recv_data[4] << 8) | recv_data[5];

    // 转换为实际值（根据AHT20数据手册公式）
    *humidity = (humidity_raw / 1048576.0f) * 100.0f;  // 1048576 = 2^20
    *temperature = (temp_raw / 1048576.0f) * 200.0f - 50.0f;

    // LCD 显示温湿度值
    // printf("~~~~~~~~~Temperature: %.2f °C, Humidity: %.2f %%~~~~~~~~~\n", *temperature, *humidity);
    if (g_is_lcd_init)
    {
        char tmp_value[16] = {0};
        sprintf(tmp_value, "%.2f ", *temperature);
        lcd_show_string(130, 80, tmp_value, LCD_BLUE, LCD_WHITE, 16, 0);
        
        char hum_value[16] = {0};
        sprintf(hum_value, "%.2f %%", *humidity);
        lcd_show_string(130, 100, hum_value, LCD_BLUE, LCD_WHITE, 16, 0);
    }

    return 0;
}
/* I2C读写函数 */
void pcf8574_write(uint8_t data) {
    uint8_t send_data[1] = {data};
    IoTI2cWrite(I2C_HANDLE, KEYBOARD_I2C_ADDRESS, send_data, 1);
    LOS_Msleep(1);
}

uint8_t pcf8574_read(void) {
    uint8_t data = 0;
    IoTI2cRead(I2C_HANDLE, KEYBOARD_I2C_ADDRESS, &data, 1);
    LOS_Msleep(1);
    return data;
}
int get_key_pressed(char *key) {
    uint32_t current_time = LOS_TickCountGet();
    uint8_t col_val;
    char new_key = '\0';
    DebounceState debounce_state = DEBOUNCE_STATE_IDLE;
    uint32_t last_debounce_time = 0;
    char debounce_key = '\0';
    
    const char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
        {'1', '2', '3', 'A'},
        {'4', '5', '6', 'B'},
        {'7', '8', '9', 'C'},
        {'*', '0', '#', 'D'}
    };

    // 扫描键盘
    for (uint8_t row = 0; row < KEYPAD_ROWS; row++) {
        pcf8574_write(~(1 << row));
        col_val = pcf8574_read() >> 4;
        
        for (uint8_t col = 0; col < KEYPAD_COLS; col++) {
            if (!(col_val & (1 << col))) {
                new_key = keys[row][col];
                break;
            }
        }
        if (new_key != '\0') 
        {
            debounce_key = DEBOUNCE_STATE_PRESS_DETECTED;
            break;
        }
    }
    // printf("key pressed: %c\n", new_key);
    *key = new_key;

    // 消抖处理
    // switch (debounce_state) {
    //     case DEBOUNCE_STATE_IDLE:
    //         if (new_key != '\0') {
    //             debounce_key = new_key;
    //             last_debounce_time = current_time;
    //             debounce_state = DEBOUNCE_STATE_PRESS_DETECTED;
    //         }
    //         break;
            
    //     case DEBOUNCE_STATE_PRESS_DETECTED:
    //         if (new_key == debounce_key) {
    //             if ((current_time - last_debounce_time) >= LOS_MS2Tick(DEBOUNCE_DELAY_MS)) {
    //                 debounce_state = DEBOUNCE_STATE_WAIT_RELEASE;
    //                 *key = debounce_key;
    //                 return 0;
    //             }
    //         } else {
    //             debounce_state = DEBOUNCE_STATE_IDLE;
    //         }
    //         break;
            
    //     case DEBOUNCE_STATE_WAIT_RELEASE:
    //         if (new_key == '\0') {
    //             debounce_state = DEBOUNCE_STATE_IDLE;
    //         }
    //         break;
    // }

    return 0;
}

/***************************************************************
* 函数名称: ws2812b_send_bit
* 说    明: 发送一个bit到WS2812B
* 参    数: 
*       uint8_t bit - 要发送的bit值（0或1）
* 返 回 值: 无
***************************************************************/
static void ws2812b_send_bit(uint8_t bit)
{
    if (bit) {
        IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE1);
        delay_us(7); // T1H = ~700ns
        IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE0);
        delay_us(6); // T1L = ~600ns
    } else {
        IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE1);
        delay_us(3); // T0H = ~350ns
        IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE0);
        delay_us(8); // T0L = ~800ns
    }
}

/***************************************************************
* 函数名称: ws2812b_send_byte
* 说    明: 发送一个字节到WS2812B
* 参    数: 
*       uint8_t byte - 要发送的字节
* 返 回 值: 无
***************************************************************/
static void ws2812b_send_byte(uint8_t byte)
{
    for (int i = 7; i >= 0; i--) {
        ws2812b_send_bit((byte >> i) & 0x01);
    }
}

/***************************************************************
* 函数名称: ws2812b_send_color
* 说    明: 发送一个RGB颜色到WS2812B灯珠
* 参    数: 
*       uint32_t color - GRB格式颜色值（例如0x00FF00为绿色）
*       int num_leds  - 灯的数量（例如10）
* 返 回 值: 无
***************************************************************/
static void ws2812b_send_color(uint32_t color, int num_leds)
{
    for (int i = 0; i < num_leds; i++) {
        // GRB顺序发送
        uint8_t green = (color >> 16) & 0xFF;
        uint8_t red   = (color >> 8)  & 0xFF;
        uint8_t blue  = (color >> 0)  & 0xFF;

        ws2812b_send_byte(green);
        ws2812b_send_byte(red);
        ws2812b_send_byte(blue);
    }
    // LOS_TaskDelay(5000);

    // 发送结束信号（低电平持续50us以上）
    // IoTGpioSetOutputVal(LIGHT_CTL_PIN, IOT_GPIO_VALUE0);
    delay_us(50);
}

/***************************************************************
* 函数名称: light_control
* 说    明: 控制WS2812B灯条状态
* 参    数: 
*       bool state - true: 打开灯条；false: 关闭灯条
* 返 回 值: 无
***************************************************************/
void light_control(bool state)
{
    static bool last_state = false;

    if (state == last_state) {
        return;
    }
    printf("Light state: %s\n", state ? "ON" : "OFF");
    if (state) {
        ws2812b_send_color(COLOR_WHITE, 10); // 设置为白色，共10个灯
    } else {
        ws2812b_send_color(COLOR_OFF, 10);   // 全部关闭
    }

    last_state = state;
}
/***************************************************************
 *  函数名称：door_control
 *  说    明：控制门锁舵机
 *  参    数：pin - 舵机控制引脚
 *             isOpen - true: 打开门锁；false: 关闭门锁
 *  返 回 值：0 - 操作成功；其他 - 操作失败
 **************************************************************/
int door_control(int pin, bool isOpen) {
    // 舵机控制参数
    if (isOpen == true)
    {
        sg90_set_angel(pin, SG90_ANGEL_90);
    }
    else
    {
        sg90_set_angel(pin, SG90_ANGEL_0);
    }

    return 0; // 操作成功
}    
